package com.openbravo.pos.printer;

import java.util.List;

import javax.usb.UsbClaimException;
import javax.usb.UsbConfiguration;
import javax.usb.UsbDevice;
import javax.usb.UsbDeviceDescriptor;
import javax.usb.UsbDisconnectedException;
import javax.usb.UsbEndpoint;
import javax.usb.UsbException;
import javax.usb.UsbInterface;
import javax.usb.UsbNotActiveException;
import javax.usb.UsbNotClaimedException;
import javax.usb.UsbNotOpenException;
import javax.usb.UsbPipe;
import javax.usb.event.UsbDeviceDataEvent;
import javax.usb.event.UsbDeviceErrorEvent;
import javax.usb.event.UsbDeviceEvent;
import javax.usb.event.UsbDeviceListener;
import javax.usb.event.UsbServicesEvent;
import javax.usb.event.UsbServicesListener;

import com.openbravo.pos.printer.escpos.PrinterWritter;


public class PrinterWritterUSB extends PrinterWritter  implements UsbDeviceListener,UsbServicesListener {
    short vendorId;
    short productId;
    UsbDevice device;
    boolean init1=false;
    private UsbPipe pipe;
    boolean detached=false;
    int intfaceNum;
    int endpointNum;
    
    /** Creates a new instance of PrinterWritterComm */
    public PrinterWritterUSB(short vendorId, short productId,int intfaceNum,int endpointNum) throws TicketPrinterException {
    	this.vendorId=vendorId;
        this.productId=productId; 
        detached=true;
        this.intfaceNum=intfaceNum;
        this.endpointNum=endpointNum;
        
   }
    
    public PrinterWritterUSB(UsbDevice device,int intfaceNum,int endpointNum) throws TicketPrinterException {
    	this.device= device;
    	UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
    	vendorId=desc.idVendor();
        productId=desc.idProduct();
        this.intfaceNum=intfaceNum;
        this.endpointNum=endpointNum;
    }
  

	protected void internalWrite(byte[] data) {
		if(detached)
    		return;
		if(!init1)
			init();
		try {
			pipe.open();
			try {
				pipe.syncSubmit(data);
			} catch (UsbNotOpenException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		} catch (UsbNotActiveException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UsbNotClaimedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UsbDisconnectedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UsbException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			try {
				pipe.close();
			} catch (UsbNotActiveException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (UsbNotOpenException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (UsbDisconnectedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (UsbException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
    }
    
    protected void internalFlush() {
       
    }
    
    protected void internalClose() {
      
    }
    
    
	private void init() {
		UsbConfiguration config = device.getActiveUsbConfiguration();
		device.addUsbDeviceListener(this);
		List totalInterfaces = config.getUsbInterfaces();
		
		// Traverse through all the interfaces, and access the endpoints
		// available to that interface for I/O.
		UsbInterface interf = (UsbInterface) totalInterfaces
				.get(intfaceNum - 1);

		try {
			interf.claim();
		} catch (UsbClaimException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UsbNotActiveException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UsbDisconnectedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UsbException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		List totalEndpoints = interf.getUsbEndpoints();
		

		// Access the particular endpoint, determine the direction
		// of its data flow, and type of data transfer, and open the
		// data pipe for I/O.
		UsbEndpoint ep = (UsbEndpoint) totalEndpoints.get(endpointNum - 1);
		int direction = ep.getDirection();
		int type = ep.getType();
		pipe = ep.getUsbPipe();
		init1 = true;
	}

	@Override
	public void dataEventOccurred(UsbDeviceDataEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void errorEventOccurred(UsbDeviceErrorEvent arg0) {
		// TODO Auto-generated method stub
		arg0.getUsbException().printStackTrace();
	}

	@Override
	public void usbDeviceDetached(UsbDeviceEvent arg0) {
		this.init1=false;
		detached=true;	
	}

	@Override
	public void usbDeviceAttached(UsbServicesEvent arg0) {
		UsbDevice device=arg0.getUsbDevice();
		UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
        if (desc.idVendor() == vendorId && desc.idProduct() == productId){
        	this.device=device;
        	this.detached=false;
        	this.init1=false;
        }
	}

	@Override
	public void usbDeviceDetached(UsbServicesEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
}
